package service.impl;

import dao.IUserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import service.IUserService;

import javax.annotation.Resource;

/**
* 业务层
 *  @Component:
 *  作用：
 *      把当前类对象交由IOC容器去实管理，类似我们之前在bean.xml中的配置
 *      <bean id = "userService" class="service.impl.UserServiceImpl"></bean>
 *  属性：
 *      value：用于指定实例化bean的id，可以不写，默认为当前类名首字母小写
 *  衍生：
 *      @Controller 一般用于表现层
 *      @Service    一般用于业务层
 *      @Repository 一般用于持久层
 *      以上为@Component的三个衍生注解，其作用与@Component是一摸一样的，
 *      他们存在的意义只是为了是我们三层架构更加清晰，他们四个可以相互替代
 *  @Autowired:
 *  作用：
 *      与与xml配置文件中<bean>标签的
 *      <property name="userDao" ref="userDao"></property>
 *      作用是一致的
 *      自动按照类型注入，只要容器中有唯一的一个bean对象类型和要注入的变量类型一致，则可以注入成功
 *      如果容器中存在两个bean的对象类型和要注入的变量类型是一致的
 *      则会首先查找到容器中的这两个bean，然后再根据要注入的变量名作为id去与找到的这两个bean去做匹配
 *      如果可以匹配到则注入成功，否则注入失败。
 *      如下面的
 *          private IUserDao userDao2;
 *      这段代码，在注入时，首先根据IUserDao接口类型去容器中查找是当前类型的bean，此时查找的结果为两个
 *      然后再根据变量名称userDao2作为id去与找到的这两个bean去做匹配
 *
 *      如果存在多个类型一致 且变量名称作为key 无法匹配到任何bean时，我们可以使用
 *      @Qualifier注解，其属性value为要注入的bean在容器中的id
 *      如下面的
 *          @Autowired
 *          @Qualifier("userDao")
 *          private IUserDao userDao3;
 *      容器中即存在多个类型一致的bean userDao3作为key去匹配时也无法匹配到
 *      那么 我们就可以使用@Qualifier注解强制去注入
 *      注意：@Qualifier注解放在对象属性上面为属性注入时无法单独使用 只能配合@Autowired一起使用
 *      但是 如果@Qualifier注解放在方法中注入， 如下
 *      public UserServiceImpl(@Qualifier("userDao")IUserDao userDao){
 *         this.userDao3 = userDao;
 *     }
 *     此时就可以单独使用
 *     如果既想放在对象属性上面还想使用一个注解的话那么就需要使用@Resource注解
 *     它既可以完成@Autowired的功能 也可以完成@Autowired@Qualifier两个注解合并的功能
 *     @Resource
 *     属性：
 *          name：IOC容器中bean对象的id
 *      如下：
 *          @Resource(name = "userDao")
 *          private IUserDao userDao4;
 *
 *  出现位置：
 *      1.要注入的属性上
 *      2.构造方法上
 *      3.set方法上
 *
 *  以上三个注解@Autowired @Qualifier @Resource 只用于Bean类型的数据注入，
 *  如果要注入基本数据类型和String类型则需要@Value注解
 *  @Value
 *      属性：
 *          value：要注入的值 支持EL表达式
 *  如下：
 *       @Value("test")
 *       private String username;
 *  @Scope
 *      作用：
 *          标注类的作用范围
 *          1.singleton：单例
 *          2.prototype：多例
 *          与xml配置文件中
 *          <bean id = "userService" class="service.impl.UserServiceImpl" scope="singleton"></bean>
 *          bean标签的scope的作用是一致的
*/
@Component
@Scope("singleton")
public class UserServiceImpl implements IUserService {

    @Resource
    private IUserDao userDao;

    @Autowired
    private IUserDao userDao2;

//    @Autowired
    @Qualifier("userDao")
    private IUserDao userDao3;

    @Resource(name = "userDao")
    private IUserDao userDao4;

    @Value("test")
    private String username;

//    @Autowired
    public UserServiceImpl(@Qualifier("userDao")IUserDao userDao){
        this.userDao3 = userDao;
    }
//    @Autowired
    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    //实例化dao
   public void saveUser() {
       System.out.println("username = " + username);
        userDao.saveUser();
        userDao2.saveUser();
        userDao3.saveUser();
        userDao4.saveUser();
  }
}